using System.Collections.Generic;
using System.Web.Mvc;
using Blog.Core.Entities;
using Blog.Infrastructure.Configuration;
using Blog.Infrastructure.DataAcces.Services.Abstractisations;
using Blog.Presentation.Controllers;
using Blog.Presentation.Models.Dislpay;
using Moq;
using NUnit.Framework;

namespace Blog.UnitTests.ControllersTests
{
    [TestFixture]
    public class ArtilceControllerTests
    {
        private ArticlesController controller;

        private Mock<IArticleService> articleService;

        [SetUp]
        public void Setup()
        {
            articleService = new Mock<IArticleService>();
            var settings = new Mock<ISettings>();
            controller = new ArticlesController(articleService.Object, settings.Object);
        }

        [Test]
        public void Action_Index_Should_Render_Index()
        {
            articleService.Setup(x => x.GetLatest(3)).Returns(new List<Article>());

            var result = controller.Index() as ViewResult;
            
            Assert.AreEqual("Index", result.ViewName);
        }

        [Test]
        public void Action_Index_Should_Render_ViewResult()
        {
            articleService.Setup(x => x.GetLatest(3)).Returns(new List<Article>());

            var result = controller.Index();

            Assert.IsInstanceOf<ViewResult>(result);
        }

        [Test]
        public void Action_Index_Should_Have_Model_List_Of_ArticleDtos()
        {
            var model = new List<Article>
                            {
                                new Article{Content = "test test test test "},
                                new Article{Content = "test test test test "},
                                new Article{Content = "test test test test "}
                            };

            articleService.Setup(x => x.GetLatest(3)).Returns(model);

            var result = controller.Index();

            Assert.IsInstanceOf<List<ArticleDto>>(result.ViewData.Model);
        }

        [Test]
        public void Action_New_Shoud_RenderView()
        {
            var result = controller.New();
            Assert.IsInstanceOf<ViewResult>(result);
        }

        [Test]
        public void Action_New_Shoud_Render_View_Having_Article_As_Model()
        {
            var result = controller.New();
            Assert.IsInstanceOf<Article>(result.ViewData.Model);
        }

        [Test]
        public void Action_New_Should_Save_Article()
        {
            articleService.Setup(x => x.Save(It.IsAny<Article>())).Verifiable();

            controller.New(new Article());

            articleService.VerifyAll();
        }

       
        [Test]
        public void Action_Detele_Should_Perform_Redirect()
        {
            var result = controller.Delete(1L);

            Assert.IsInstanceOf<RedirectToRouteResult>(result);
        }

        [Test] 
        public void Action_Delete_For_An_Existing_Id_Invoke_Delete_Method()
        {
            articleService.Setup(x => x.Delete(1)).Verifiable();
            
            var result = controller.Delete(1);
            
            articleService.Verify();

        }

        [Test]
        public void Action_Edit_Should_Render_View()
        {
            var result = controller.Edit(1);

            Assert.IsInstanceOf<ViewResult>(result);
        }

        [Test]
        public void Action_Edit_Should_Render_View_Having_Model_Article()
        {
            articleService.Setup(x => x.Get(1)).Returns(new Article());
            var result = controller.Edit(1);

            Assert.IsInstanceOf<Article>(result.ViewData.Model);
        }

        [Test]
        public void Action_HttpPost_Edit_Should_Redirect()
        {
            var result = controller.Edit(new Article());

            Assert.IsInstanceOf<RedirectToRouteResult>(result);
        }

        [Test]
        public void Action_HttpPost_Edit_Should_Invoke_Save_Method()
        {
            var art = new Article();
            articleService.Setup(x => x.Save(art)).Verifiable();
            
            var result = controller.Edit(art);

            articleService.VerifyAll();
        }

        [Test]
        public void Action_View_Should_Render_View()
        {
            articleService.Setup(x => x.Get(1)).Returns(new Article());
            var result = controller.View(1.ToString());

            Assert.IsInstanceOf<ViewResult>(result);
        }

        [Test]
        public void Action_View_Should_Invoke_Get_Service_Method()
        {
            articleService.Setup(x => x.Get(1)).Returns(new Article()).Verifiable();
            
            var result = controller.View(1.ToString());

            articleService.VerifyAll();
        }

        [Test]
        public void Action_View_Shoul_Increment_Number_Artricle_Views()
        {
            var article = new Article{Title = 1.ToString()};
            articleService.Setup(x => x.Get(1.ToString())).Returns(article).Verifiable();
            articleService.Setup(x => x.Save(article)).Verifiable();

            var result = controller.View(1.ToString());

            Assert.That(article.Views == 1);
        }

        [Test]
        public void Action_Category_Invokes_ByCategory_Service_Method()
        {
            articleService.Setup(x => x.ByCategory(It.IsAny<string>()));

            controller.CategoryView("test");

            articleService.VerifyAll();
        }
    }
}